// src/main/java/com/cupk/services/ProjectService.java (最终修复版 - 明确泛型类型)

package com.cupk.services;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cupk.dtos.CreateProjectRequest;
import com.cupk.dtos.PageDto; // 确保导入 PageDto
import com.cupk.dtos.ProjectDto; // 确保导入 ProjectDto
import com.cupk.dtos.UpdateProjectRequest;
import com.cupk.entities.Project;
import com.cupk.entities.ProjectMember;
import com.cupk.entities.User;
import com.cupk.exceptions.ResourceAlreadyExistsException;
import com.cupk.exceptions.ResourceNotFoundException;
import com.cupk.mapper.ProjectMapper;
import com.cupk.mapper.ProjectMemberMapper;
import com.cupk.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import com.cupk.dtos.UpdateProjectRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ProjectService {

    private final ProjectMapper projectMapper;
    private final UserMapper userMapper;
    private final ProjectMemberMapper projectMemberMapper;

    @Transactional
    public ProjectDto createProject(CreateProjectRequest request) {
        if (request.getProjectCode() != null && !request.getProjectCode().isEmpty()) {
            if (projectMapper.exists(new QueryWrapper<Project>().eq("project_code", request.getProjectCode()))) {
                throw new ResourceAlreadyExistsException("错误：项目代码 '" + request.getProjectCode() + "' 已存在。");
            }
        }

        User principalInvestigator = userMapper.selectById(request.getPrincipalInvestigatorId());
        if (principalInvestigator == null) {
            throw new ResourceNotFoundException("未找到指定的项目负责人，ID: " + request.getPrincipalInvestigatorId());
        }

        Project project = new Project();
        project.setProjectName(request.getProjectName());
        project.setProjectCode(request.getProjectCode());
        project.setDescription(request.getDescription());
        project.setStartDate(request.getStartDate());
        project.setEndDate(request.getEndDate());
        project.setStatus(request.getStatus());
        project.setBudgetAmount(request.getBudgetAmount());
        projectMapper.insert(project);

        ProjectMember projectMember = new ProjectMember();
        projectMember.setProjectId(project.getId());
        projectMember.setUserId(principalInvestigator.getId());
        projectMember.setRoleInProject("PI");
        projectMemberMapper.insert(projectMember);

        return convertToDto(project, principalInvestigator.getFullName());
    }

    @Transactional(readOnly = true)
    public PageDto<ProjectDto> findProjectsByPage(
            int pageNum,
            int pageSize,
            String projectName,
            String projectCode
    ) {
        Page<Project> page = new Page<>(pageNum, pageSize);

        QueryWrapper<Project> queryWrapper = new QueryWrapper<>();
        if (StringUtils.hasText(projectName)) {
            queryWrapper.like("project_name", projectName);
        }
        if (StringUtils.hasText(projectCode)) {
            queryWrapper.like("project_code", projectCode);
        }
        queryWrapper.orderByDesc("created_at");

        Page<Project> projectPage = projectMapper.selectPage(page, queryWrapper);

        List<ProjectDto> projectDtoList = projectPage.getRecords().stream()
                .map(project -> {
                    String piName = findPrincipalInvestigatorNameByProjectId(project.getId()).orElse("未分配");
                    return convertToDto(project, piName);
                })
                .collect(Collectors.toList());

        // 【核心修改】: 明确指定泛型类型 ProjectDto
        PageDto<ProjectDto> dtoPage = new PageDto<ProjectDto>(); // 明确指定泛型
        dtoPage.setRecords(projectDtoList);
        dtoPage.setTotal(projectPage.getTotal());
        dtoPage.setSize(projectPage.getSize());
        dtoPage.setCurrent(projectPage.getCurrent());
        dtoPage.setPages(projectPage.getPages());

        return dtoPage;
    }

    public ProjectDto getProjectById(Long id) {
        Project project = projectMapper.selectById(id);
        if (project == null) {
            throw new ResourceNotFoundException("未找到项目，ID: " + id);
        }
        String piName = findPrincipalInvestigatorNameByProjectId(id).orElse("未分配");
        return convertToDto(project, piName);
    }

    @Transactional
    public ProjectDto updateProject(Long id, UpdateProjectRequest request) {
        Project project = projectMapper.selectById(id);
        if (project == null) {
            throw new ResourceNotFoundException("未找到项目，ID: " + id);
        }

        // 检查项目代码是否被其他项目占用
        if (request.getProjectCode() != null && !request.getProjectCode().isEmpty()) {
            Project existingProject = projectMapper.selectOne(new QueryWrapper<Project>().eq("project_code", request.getProjectCode()));
            if (existingProject != null && !existingProject.getId().equals(id)) {
                throw new ResourceAlreadyExistsException("错误：项目代码 '" + request.getProjectCode() + "' 已被其他项目占用。");
            }
        }

        // 更新项目信息：确保只更新请求中非空的字段
        if (request.getProjectName() != null) {
            project.setProjectName(request.getProjectName());
        }
        if (request.getProjectCode() != null) {
            project.setProjectCode(request.getProjectCode());
        }
        if (request.getDescription() != null) {
            project.setDescription(request.getDescription());
        }
        if (request.getStartDate() != null) {
            project.setStartDate(request.getStartDate());
        }
        if (request.getEndDate() != null) {
            project.setEndDate(request.getEndDate());
        }
        if (request.getStatus() != null) {
            project.setStatus(request.getStatus());
        }
        if (request.getBudgetAmount() != null) {
            project.setBudgetAmount(request.getBudgetAmount());
        }

        // 处理项目负责人更新 (与之前逻辑类似)
        if (request.getPrincipalInvestigatorId() != null) {
            User newPrincipalInvestigator = userMapper.selectById(request.getPrincipalInvestigatorId());
            if (newPrincipalInvestigator == null) {
                throw new ResourceNotFoundException("未找到指定的项目负责人，ID: " + request.getPrincipalInvestigatorId());
            }
            ProjectMember piMember = projectMemberMapper.selectOne(new QueryWrapper<ProjectMember>()
                    .eq("project_id", id)
                    .eq("role_in_project", "PI"));

            if (piMember != null) {
                piMember.setUserId(newPrincipalInvestigator.getId());
                projectMemberMapper.updateById(piMember);
            } else {
                ProjectMember newMember = new ProjectMember();
                newMember.setProjectId(id);
                newMember.setUserId(newPrincipalInvestigator.getId());
                newMember.setRoleInProject("PI");
                projectMemberMapper.insert(newMember);
            }
        }

        project.setUpdatedAt(LocalDateTime.now()); // 更新时间
        projectMapper.updateById(project);

        // 返回更新后的 DTO，需要重新获取 PI Name
        String piName = findPrincipalInvestigatorNameByProjectId(id).orElse("未分配");
        return convertToDto(project, piName);
    }
    @Transactional
    public void deleteProject(Long id) {
        if (!projectMapper.exists(new QueryWrapper<Project>().eq("id", id))) {
            throw new ResourceNotFoundException("删除失败：未找到项目，ID: " + id);
        }
        projectMemberMapper.delete(new QueryWrapper<ProjectMember>().eq("project_id", id));
        projectMapper.deleteById(id);
    }

    public boolean canUserModifyProject(Long projectId, String username) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
        if (user == null) {
            return false;
        }
        if ("ADMIN".equals(user.getRole())) {
            return true;
        }

        List<String> permittedRoles = Arrays.asList("PI", "CO_PI");

        // 确保 projectMemberMapper 有 countByProjectAndUserAndRoles 方法 或者使用 exists
        // 这里沿用之前的 exists 方式，避免引入新 Mapper 方法
        return projectMemberMapper.exists(new QueryWrapper<ProjectMember>()
                .eq("project_id", projectId)
                .eq("user_id", user.getId())
                .in("role_in_project", permittedRoles));
    }

    @Transactional(readOnly = true)
    public List<ProjectDto> findProjectsByUsername(String username) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
        if (user == null) {
            throw new ResourceNotFoundException("用户未找到: " + username);
        }

        List<ProjectMember> memberships = projectMemberMapper.selectList(new QueryWrapper<ProjectMember>().eq("user_id", user.getId()));
        if (memberships.isEmpty()) {
            return new ArrayList<>();
        }

        List<Long> projectIds = memberships.stream()
                .map(ProjectMember::getProjectId)
                .collect(Collectors.toList());

        return projectMapper.findAllWithPiName().stream()
                .filter(p -> projectIds.contains(p.getId()))
                .collect(Collectors.toList());
    }

    private Optional<String> findPrincipalInvestigatorNameByProjectId(Long projectId) {
        ProjectMember pm = projectMemberMapper.selectOne(new QueryWrapper<ProjectMember>()
                .eq("project_id", projectId)
                .eq("role_in_project", "PI"));

        if (pm == null) {
            return Optional.empty();
        }
        User user = userMapper.selectById(pm.getUserId());
        return user != null ? Optional.ofNullable(user.getFullName()) : Optional.empty();
    }

    private ProjectDto convertToDto(Project project, String piName) {
        ProjectDto dto = new ProjectDto();
        dto.setId(project.getId());
        dto.setProjectName(project.getProjectName());
        dto.setProjectCode(project.getProjectCode());
        dto.setDescription(project.getDescription());
        dto.setStartDate(project.getStartDate());
        dto.setEndDate(project.getEndDate());
        dto.setStatus(project.getStatus());
        dto.setBudgetAmount(project.getBudgetAmount());
        dto.setPrincipalInvestigatorName(piName);
        return dto;
    }
    @Transactional(readOnly = true)
    public List<ProjectDto> getAllProjectsNoPagination() {
        // 直接调用 Mapper 获取所有，Mapper 已经有了 findAllWithPiName
        return projectMapper.findAllWithPiName();
    }
}